`timescale 1ns/1ps
`default_nettype none

/* NOTE:
* - 本模负责进行缝隙调整
* - 每3个周期完成一次计算
* - 依次计算RGB，每个周期读入相应系数
* - 输入/输出RGB为16bit无符号数
* - 系数为16bit无符号数，15bit小数位
*/

module gap_adjust (
    // system signal
    input  wire         I_sclk,
    input  wire         I_rst_n,
    // adjust enable
    input  wire         I_adjust_en,
    // coefficient
    output wire         O_coe_ack,
    input  wire [15:0]  I_coe_val,
    // input pixel
    input  wire         I_data_en,
    input  wire [15:0]  I_data_in,
    // result
    output wire         O_valid,
    output wire [15:0]  O_r_out,
    output wire [15:0]  O_g_out,
    output wire [15:0]  O_b_out
);
//------------------------Parameter----------------------

//------------------------Local signal-------------------
reg         data_en;
reg         data_en_2;
reg  [15:0] data_in;
reg  [15:0] data_in_2;
reg  [2:0]  color;
reg  [31:0] result;
reg         valid;
reg  [15:0] r_val;
reg  [15:0] g_val;
reg  [15:0] b_val;
reg  [15:0] coe_val;

//------------------------Instantiation------------------

//------------------------Body---------------------------
//assign result = coe_val * data_in;
always@(posedge I_sclk)
    result <= coe_val * data_in;

assign O_valid = valid;
assign O_r_out = r_val;
assign O_g_out = g_val;
assign O_b_out = b_val;

assign O_coe_ack = data_en_2 && color[0];

// data_en
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        data_en <= 1'b0;
    else
        data_en <= I_data_en;
end

// data_en_2
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        data_en_2 <= 1'b0;
    else
        data_en_2 <= data_en;
end

// data_in
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        data_in <= 1'b0;
    else
        data_in <= I_data_in;
end

// data_in_2
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        data_in_2 <= 1'b0;
    else
        data_in_2 <= data_in;
end

// color
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        color <= 1'b1;
    else if (data_en_2)
        color <= {color[1:0], color[2]};
end

// valid
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        valid <= 1'b0;
    else
        valid <= data_en_2 && color[2];
end

// r_val
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        r_val <= 1'b0;
    else if (data_en_2 && color[0]) begin
        if (!I_adjust_en)
            r_val <= data_in_2;
        else if (result[31])
            r_val <= 16'hffff;
        else
            r_val <= result[30:15];
    end
end

// g_val
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        g_val <= 1'b0;
    else if (data_en_2 && color[1]) begin
        if (!I_adjust_en)
            g_val <= data_in_2;
        else if (result[31])
            g_val <= 16'hffff;
        else
            g_val <= result[30:15];
    end
end

// b_val
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        b_val <= 1'b0;
    else if (data_en_2 && color[2]) begin
        if (!I_adjust_en)
            b_val <= data_in_2;
        else if (result[31])
            b_val <= 16'hffff;
        else
            b_val <= result[30:15];
    end
end

// coe_val
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        coe_val <= 1'b0;
    else if (I_data_en)
        coe_val <= I_coe_val;
end

endmodule

`default_nettype wire

// vim:set ts=4 sw=4 et fenc=utf-8 fdm=marker:
